package com.jike.jkgame;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.jike.jkgame.AttackPreviewDialog.OnActionListener;
import com.jike.jkgame.AttackResultDialog.OnAttackWinListner;
import com.jike.jkgame.data.AttackPreviewData;
import com.jike.jkgame.data.AttackResultData;
import com.jike.jkgame.data.Player;
import com.jike.jkgame.data.PlayerCompareData;
import com.jike.jkgame.data.PlayerDetail;
import com.jike.jkgame.data.SimpleGeneral;
import com.jike.jkgame.data.UserStatus;
import com.jike.jkgame.exception.EncodingException;
import com.jike.jkgame.exception.NetworkErrorException;
import com.jike.jkgame.network.MessageFactory;
import com.jike.jkgame.network.NetworkUtilis;
import com.jike.jkgame.network.ServerConfig;

public class AttackFragment extends Fragment implements OnClickListener,
		OnActionListener, OnAttackWinListner {

	private static final int VS = 0;
	private static final int ENEMY = 1;

	private View mTabVS;
	private View mTabEnemis;
	private ListView mPlayersLv;
	private List<Player> mPlayers;
	private int mCurPlayer;

	private LayoutInflater mInflater;
	private PalyersAdapter mListAdaper;
	private ProgressBar mProgress;
	private int mAttackType = VS;
	private GetPlayerListTask mGetTask;
	private AnimationDialog mAnimDialog;
	private View mUserStatusView;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		mInflater = LayoutInflater.from(getActivity());
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View v = inflater.inflate(R.layout.attack_layout, container, false);
		mTabVS = v.findViewById(R.id.tab_vs);
		mTabEnemis = v.findViewById(R.id.tab_enemies);
		mProgress = (ProgressBar) v.findViewById(R.id.pb_conecting);

		mPlayersLv = (ListView) v.findViewById(R.id.lv_players);
		
		mUserStatusView = v.findViewById(R.id.user_status);

		mTabVS.setSelected(true);
		mAttackType = VS;

		mTabVS.setOnClickListener(this);
		mTabEnemis.setOnClickListener(this);
		v.findViewById(R.id.btn_refresh).setOnClickListener(this);

		mListAdaper = new PalyersAdapter();
		mPlayersLv.setAdapter(mListAdaper);

		getPlayers(mAttackType);

		mAnimDialog = new AnimationDialog();
		return v;
	}

	@Override
	public void onClick(View v) {

		switch (v.getId()) {
		case R.id.tab_vs:
			if (!v.isSelected()) {
				v.setSelected(true);
				mTabEnemis.setSelected(false);
				mAttackType = VS;
			}
			break;
		case R.id.tab_enemies:
			if (!v.isSelected()) {
				v.setSelected(true);
				mTabVS.setSelected(false);
				mAttackType = ENEMY;
			}
			break;
		case R.id.btn_refresh:
			getPlayers(mAttackType);
		default:
			break;
		}

		getPlayers(mAttackType);
	}

	private void getPlayers(int type) {
		if (mGetTask != null
				&& mGetTask.getStatus() != AsyncTask.Status.FINISHED) {
			mGetTask.cancel(true);
		}
		mGetTask = new GetPlayerListTask();
		mGetTask.execute(type);
	}

	private void showAttackPreviewDialog(AttackPreviewData data) {
		AttackPreviewDialog dialog = AttackPreviewDialog
				.newInstance(this, data);
		dialog.show(getActivity().getSupportFragmentManager(), "vsdialog");
	}

	private void showShortageDialog() {
		ShortageAlertFragmentDialog dialog = ShortageAlertFragmentDialog
				.newInstance("health");
		dialog.show(getActivity().getSupportFragmentManager(),
				"shortage_strength");
	}

	private void showAttackResultDialog(AttackResultData data) {
		AttackResultDialog dialog = AttackResultDialog.newInstance(this, data);

		dialog.show(getActivity().getSupportFragmentManager(), "attack_result");
	}

	private List<Player> parsPlayerList(JSONArray json) {
		if (json == null) {
			return null;
		}

		List<Player> players = new ArrayList<Player>(json.length());

		for (int i = 0; i < json.length(); ++i) {

			JSONObject j = json.optJSONObject(i);
			if (j != null) {
				Player p = new Player();
				p.rid = j.optInt("rid");
				p.level = j.optInt("level");
				p.rname = j.optString("rname");
				p.att_min = j.optInt("att_low");
				p.att_max = j.optInt("att_high");
				p.robot = j.optBoolean("bot");
				players.add(p);
			}
		}
		return players;
	}

	private void previewAttack(Player player) {
		GetPreviewAttackTask task = new GetPreviewAttackTask();
		task.execute(player);
	}
	
	@Override
	public void onResume() {
		super.onResume();
		UserStatusViewManager.get().bindView(mUserStatusView);
	}


	class PalyersAdapter extends BaseAdapter {

		@Override
		public int getCount() {
			if (mPlayers == null) {
				return 0;
			}
			return mPlayers.size();
		}

		@Override
		public Object getItem(int position) {
			return null;
		}

		@Override
		public long getItemId(int position) {
			return 0;
		}

		@Override
		public View getView(final int position, View convertView,
				ViewGroup parent) {
			View v = convertView;
			if (v == null) {
				v = mInflater.inflate(R.layout.player_list_item, parent, false);
			}

			TextView tv = (TextView) v.findViewById(R.id.tv_info);

			mCurPlayer = position;
			tv.setText(mPlayers.get(mCurPlayer).getFormatedString());
			Button btn = (Button) v.findViewById(R.id.btn_attack);
			btn.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					previewAttack(mPlayers.get(position));
				}
			});
			return v;
		}

	}

	class GetPlayerListTask extends AsyncTask<Integer, Integer, List<Player>> {

		@Override
		protected List<Player> doInBackground(Integer... params) {

			if (params == null || params.length <= 0) {
				return null;
			}

			int type = params[0];
			List<Player> players = null;

			JSONObject req = type == VS ? MessageFactory
					.createGetVSPlayerListReqMessage() : MessageFactory
					.createGetEnemiesReqMessage();

			try {
				String response = NetworkUtilis.getHttpString(ServerConfig
						.get().getGameServer(), req);

				if (response != null) {
					JSONObject json = new JSONObject(response);

					int opcode = json.optInt("opcode", -1);

					if (opcode != 0) {
						return null;
					}

					JSONArray playersjson = json
							.optJSONArray(type == VS ? "opponents" : "enemies");
					players = parsPlayerList(playersjson);
				}

			} catch (NetworkErrorException e) {
				e.printStackTrace();
			} catch (EncodingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}

			return players;
		}

		@Override
		protected void onPreExecute() {
			mProgress.setVisibility(View.VISIBLE);
			super.onPreExecute();
		}

		@Override
		protected void onPostExecute(List<Player> result) {
			super.onPostExecute(result);
			mPlayers = result;
			mListAdaper.notifyDataSetChanged();

			mProgress.setVisibility(View.GONE);
		}

	}

	class GetPreviewAttackTask extends
			AsyncTask<Player, Integer, AttackPreviewData> {

		@Override
		protected AttackPreviewData doInBackground(Player... params) {
			if (params == null || params.length <= 0) {
				return null;
			}

			Player player = params[0];

			JSONObject req = MessageFactory
					.createGetAttackPreviewReqMessage(player);

			try {
				String response = NetworkUtilis.getHttpString(ServerConfig
						.get().getGameServer(), req);

				if (response == null) {
					return null;
				}
				AttackPreviewData previewData = new AttackPreviewData();
				previewData.defense = player;

				JSONObject json = new JSONObject(response);
				previewData.opcode = json.optInt("opcode");

				if (previewData.opcode == 0) {

					JSONObject jobj = json.optJSONObject("win");
					if (jobj != null) {
						previewData.winExp = jobj.optInt("exp");
						previewData.winMoney = jobj.optInt("money");
					}
					jobj = json.optJSONObject("fail");
					if (jobj != null) {
						previewData.failExp = jobj.optInt("exp");
						previewData.failMoney = jobj.optInt("money");
					}
				}

				return previewData;

			} catch (NetworkErrorException e) {
				e.printStackTrace();
			} catch (EncodingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}

			return null;
		}

		@Override
		protected void onPostExecute(AttackPreviewData result) {
			super.onPostExecute(result);
			mProgress.setVisibility(View.GONE);

			if (result == null) {
				return;
			}

			if (result.opcode == 0) {
				showAttackPreviewDialog(result);
			} else if (result.opcode == 451) {
				showShortageDialog();
			}

		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			mProgress.setVisibility(View.VISIBLE);
		}

	}

	class AttackTask extends AsyncTask<Player, Integer, AttackResultData> {

		@Override
		protected AttackResultData doInBackground(Player... params) {
			if (params == null || params.length <= 0) {
				return null;
			}

			long start = System.currentTimeMillis();

			Player player = params[0];

			JSONObject req = MessageFactory.createGetAttackReqMessage(player);

			AttackResultData result = null;
			try {
				String response = NetworkUtilis.getHttpString(ServerConfig
						.get().getGameServer(), req);

				if (response == null) {
					return null;
				}
				result = new AttackResultData();
				JSONObject json = new JSONObject(response);
				result.opcode = json.optInt("opcode", -1);
				result.player = player;
				if (result.opcode == 0) {
					result.result = json.optInt("result");
					result.exp = json.optInt("exp");
					result.money = json.optInt("money");
					result.equip = json.optInt("equip");
					result.vigour = json.optInt("vigour");
				}

			} catch (NetworkErrorException e) {
				e.printStackTrace();
			} catch (EncodingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}

			long remain = 2000 + start - System.currentTimeMillis();
			if (remain > 0) {
				try {
					Thread.sleep(remain);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

			return result;
		}

		@Override
		protected void onPostExecute(AttackResultData result) {
			super.onPostExecute(result);
			
			if (result == null || result.opcode != 0) {
				return;
			}
			
			showAttackResultDialog(result);
			// mProgress.setVisibility(View.GONE);
			mAnimDialog.dismiss();

			UserStatus user = UserStatus.get();
			user.addExpierence(result.exp);
			user.addMoney(result.money);
			user.useVigour(result.vigour);

			((MainActivity) getActivity())
					.updateUserStatus(UserStatusFragment.MONEY
							| UserStatusFragment.EXPERIENCE
							| UserStatusFragment.VIGOUR);
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			// mProgress.setVisibility(View.VISIBLE);
			mAnimDialog.show(getActivity().getSupportFragmentManager(), "anim");
		}

	}

	private static PlayerDetail parsPlayerDetail(JSONObject json, boolean attack) {
		if (json == null) {
			return null;
		}

		PlayerDetail player = new PlayerDetail();
		player.attack = attack;
		player.rid = json.optInt("rid");
		player.rname = json.optString("rname");
		player.level = json.optInt("level");
		player.army = json.optInt(attack ? "army_att" : "army_def");
		player.base = json.optInt(attack ? "base_att" : "base_def");

		JSONArray team = json.optJSONArray("team");
		if (team != null) {
			int len = team.length();
			player.team = new ArrayList<SimpleGeneral>(len);

			for (int i = 0; i < len; ++i) {
				SimpleGeneral g = new SimpleGeneral();
				JSONObject gobj = team.optJSONObject(i);
				g.gid = gobj.optInt("gid");
				g.value = gobj.optInt(attack ? "attack" : "defense");
				player.team.add(g);
			}

		}

		return player;
	}

	class ComparePlayerTask extends
			AsyncTask<Player, Integer, PlayerCompareData> {

		@Override
		protected PlayerCompareData doInBackground(Player... params) {
			if (params == null || params.length <= 0) {
				return null;
			}
			Player player = params[0];

			JSONObject req = MessageFactory.createGetCompareReqMessage(player);

			PlayerCompareData result = null;
			try {
				String response = NetworkUtilis.getHttpString(ServerConfig
						.get().getGameServer(), req);
				if (response == null) {
					return null;
				}
				result = new PlayerCompareData();
				JSONObject json = new JSONObject(response);
				result.opcode = json.optInt("opcode", -1);

				if (result.opcode == 0) {
					JSONObject p = json.optJSONObject("attack");
					result.attack = parsPlayerDetail(p, true);
					p = json.optJSONObject("defense");
					result.defense = parsPlayerDetail(p, false);
				}

			} catch (NetworkErrorException e) {
				e.printStackTrace();
			} catch (EncodingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}

			return result;
		}

		@Override
		protected void onPostExecute(PlayerCompareData result) {
			super.onPostExecute(result);
			mProgress.setVisibility(View.GONE);
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			mProgress.setVisibility(View.VISIBLE);
		}

	}

	@Override
	public void doAttack(Player player) {
		AttackTask task = new AttackTask();
		task.execute(player);

	}

	@Override
	public void cancel(Player player) {

	}

	@Override
	public void compare(Player player) {
		ComparePlayerTask task = new ComparePlayerTask();
		task.execute(player);

	}

}
